package com.ctshk.rpc.finance.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.CollectionWayCode;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.common.vo.OrderRefundDTO;
import com.ctshk.rpc.finance.code.CollectionWayIdCode;
import com.ctshk.rpc.finance.dto.bill.*;
import com.ctshk.rpc.finance.entity.FinanceBill;
import com.ctshk.rpc.finance.entity.FinanceBillGroupRecord;
import com.ctshk.rpc.finance.json.AccountJson;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.mapper.FinanceBillConfirmMapper;
import com.ctshk.rpc.finance.mapper.FinanceBillGroupRecordMapper;
import com.ctshk.rpc.finance.mapper.FinanceBillMapper;
import com.ctshk.rpc.finance.req.bill.*;
import com.ctshk.rpc.finance.req.onaccount.RollBackQuotaReq;
import com.ctshk.rpc.finance.service.IFinanceBillService;
import com.ctshk.rpc.finance.service.IFinanceOnAccountCurrencyQuotaService;
import com.ctshk.rpc.order.air.service.IAirOrderService;
import com.ctshk.rpc.order.airexpress.service.IAirportExpressOrderRefundService;
import com.ctshk.rpc.order.airexpress.service.IAirportExpressOrderService;
import com.ctshk.rpc.order.bus.service.IBusOrderRefundService;
import com.ctshk.rpc.order.bus.service.IBusOrderService;
import com.ctshk.rpc.order.custom.service.ICustomizedOrderTouristRefundService;
import com.ctshk.rpc.order.goods.req.CommodityOrderRefundReq;
import com.ctshk.rpc.order.goods.service.IOrderCommodityRefundService;
import com.ctshk.rpc.order.goods.service.IOrderService;
import com.ctshk.rpc.order.hotel.service.IHotelOrderCenterService;
import com.ctshk.rpc.order.localfun.service.ILocalFunOrderRefundService;
import com.ctshk.rpc.order.scenic.service.IScenicOrderRefundService;
import com.ctshk.rpc.order.ship.service.IShipOrderService;
import com.ctshk.rpc.order.tour.service.ISeriesOrderTouristRefundService;
import com.ctshk.rpc.order.train.service.ITrainOrderRefundService;
import com.ctshk.rpc.order.train.service.ITrainOrderService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.dto.mian.data.MainDataSubjectDTO;
import com.ctshk.rpc.system.service.IMainDataSubjectService;
import com.ctshk.rpc.system.service.ISysUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 财务收款及退款单 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-03-26
 */
@DubboService
public class FinanceBillServiceImpl extends ServiceImpl<FinanceBillMapper, FinanceBill> implements IFinanceBillService {

    @Autowired
    private FinanceBillMapper billMapper;
    @Autowired
    private FinanceBillConfirmMapper billConfirmMapper;
    @Autowired
    private FinanceBillGroupRecordMapper billGroupRecordMapper;
    @Autowired
    private IFinanceOnAccountCurrencyQuotaService financeOnAccountCurrencyQuotaService;

    @DubboReference
    private ISysUserService sysUserService;
    //机票
    @DubboReference
    private IAirOrderService airOrderService;
    //定制报团
    @DubboReference
    private ICustomizedOrderTouristRefundService customizedOrderTouristRefundService;
    //门票退款
    @DubboReference
    private IScenicOrderRefundService scenicOrderRefundService;
    //旅行团
    @DubboReference
    private ISeriesOrderTouristRefundService seriesOrderTouristRefundService;
    //机场快线
    @DubboReference
    private IAirportExpressOrderService airportExpressOrderService;
    @DubboReference
    private IAirportExpressOrderRefundService airportExpressOrderRefundService;
    @DubboReference
    private ILocalFunOrderRefundService localFunOrderRefundService;
    @DubboReference
    private IBusOrderRefundService busOrderRefundService;
    @DubboReference
    private IBusOrderService busOrderService;
    @DubboReference
    private IShipOrderService shipOrderService;
    @DubboReference
    private ITrainOrderRefundService trainOrderRefundService;
    @DubboReference
    private ITrainOrderService trainOrderService;
    @DubboReference
    private IOrderService orderService;
    @DubboReference
    private IOrderCommodityRefundService orderCommodityRefundService;
    @DubboReference
    private IMainDataSubjectService mainDataSubjectService;
    @DubboReference
    private IHotelOrderCenterService hotelOrderCenterService;




    /**
     * 认款列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillListDTO>> list(BillListReq req) {
        Page<BillListDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        Page<BillListDTO> page = billMapper.queryListByCondition(iPage,req);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        List<BillListDTO> list = new ArrayList<>();
        page.getRecords().forEach(dto -> {
            if (StringUtils.isNotBlank(dto.getCollectionVoucherJson())){
                List<FileJson> fileJsons = JSON.parseArray(dto.getCollectionVoucherJson(), FileJson.class);
                dto.setFileJsons(fileJsons);
            }
            //查询销售
            if (dto.getSaleUserId() != null){
                UserDTO userDto = sysUserService.queryCacheUser(dto.getSaleUserId());
                if (userDto != null){
                    dto.setSaleDept(userDto.getDept());
                }
            }
            //查询认款人
            if (dto.getConfirmUserId() != null){
                UserDTO confirmUserDto = sysUserService.queryCacheUser(dto.getConfirmUserId());
                if (confirmUserDto != null){
                    dto.setConfirmUserDept(confirmUserDto.getDept());
                }
            }
            if (dto.getConfirmStatus() == null){
                dto.setConfirmStatus(1);
            }
            list.add(dto);
        });
        PageResponse<BillListDTO> result = new PageResponse<>(
                list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 待确认列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillToConfirmListDTO>> toConfirmList(BillToConfirmListReq req) {
        Page<FinanceBill> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<FinanceBill> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("bill_type",1);
        queryWrapper.eq("is_deleted",0);
        queryWrapper.isNull("confirm_id");
        queryWrapper.eq(req.getBusinessType() != null,"business_type",req.getBusinessType());
        queryWrapper.eq(req.getCreateDeptId() != null,"create_dept_id",req.getCreateDeptId());
        queryWrapper.eq(req.getCollectionWayId() != null,"collection_way_id",req.getCollectionWayId());
        queryWrapper.eq(req.getCollectionTypeId() != null,"collection_type_id",req.getCollectionTypeId());
        queryWrapper.eq(req.getSaleUserId() != null,"sale_user_id",req.getSaleUserId());
        queryWrapper.between(req.getCollectDateBegin() != null && req.getCollectDateEnd() != null,"collection_time",req.getCollectDateBegin(),req.getCollectDateEnd());
        queryWrapper.like(StringUtils.isNotBlank(req.getBillNumber()),"bill_number",req.getBillNumber());
        queryWrapper.like(StringUtils.isNotBlank(req.getProductName()),"product_name",req.getProductName());
        queryWrapper.like(StringUtils.isNotBlank(req.getProductNumber()),"product_number",req.getProductNumber());
        queryWrapper.orderByDesc("gmt_create");
        Page<FinanceBill> page = billMapper.selectPage(iPage, queryWrapper);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        List<BillToConfirmListDTO> list = new ArrayList<>();
        page.getRecords().forEach(item -> {
            BillToConfirmListDTO dto = EntityUtil.copy(item,BillToConfirmListDTO.class);
            //查询销售
            if (item.getSaleUserId() != null){
                UserDTO userDto = sysUserService.queryCacheUser(item.getSaleUserId());
                if (userDto != null){
                    dto.setSaleDept(userDto.getDept());
                }
            }
            list.add(dto);
        });
        PageResponse<BillToConfirmListDTO> result = new PageResponse<>(
                list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 批量ID获取列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillToConfirmListDTO>> batchIdList(BillBatchIdListListReq req) {
        Page<FinanceBill> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<FinanceBill> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("bill_type",1);
        queryWrapper.eq("is_deleted",0);
        queryWrapper.isNull("confirm_id");
        if (req.getIdList() != null && req.getIdList().size() > 0){
            queryWrapper.in("id",req.getIdList());
        }
        Page<FinanceBill> page = billMapper.selectPage(iPage, queryWrapper);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        List<BillToConfirmListDTO> list = new ArrayList<>();
        page.getRecords().forEach(item -> {
            BillToConfirmListDTO dto = EntityUtil.copy(item,BillToConfirmListDTO.class);
            if (item.getSaleUserId() != null){
                UserDTO userDto = sysUserService.queryCacheUser(item.getSaleUserId());
                if (userDto != null){
                    dto.setSaleDept(userDto.getDept());
                }
            }
            list.add(dto);
        });
        PageResponse<BillToConfirmListDTO> result = new PageResponse<>(
                list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 根据认款ID获取列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillToConfirmListDTO>> confirmList(BillConfirmIdListReq req) {
        Page<FinanceBill> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<FinanceBill> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("confirm_id",req.getConfirmId());
        queryWrapper.eq("is_deleted",0);
        Page<FinanceBill> page = billMapper.selectPage(iPage, queryWrapper);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        List<BillToConfirmListDTO> list = new ArrayList<>();
        page.getRecords().forEach(item -> {
            BillToConfirmListDTO dto = EntityUtil.copy(item,BillToConfirmListDTO.class);
            if (item.getSaleUserId() != null){
                UserDTO userDto = sysUserService.queryCacheUser(item.getSaleUserId());
                if (userDto != null){
                    dto.setSaleDept(userDto.getDept());
                }
            }
            list.add(dto);
        });
        PageResponse<BillToConfirmListDTO> result = new PageResponse<>(
                list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 客户对账-客户未对账列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillToConfirmListDTO>> customUncheckList(BillCustomIdListReq req) {
        Page<FinanceBill> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<FinanceBill> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("big_client_id",req.getBigClientId());
        queryWrapper.eq("check_bill_status",0);
        queryWrapper.eq("is_deleted",0);
        queryWrapper.eq(req.getCreateDeptId() != null,"create_dept_id",req.getCreateDeptId());
        queryWrapper.between(req.getGmtCreateBegin() != null && req.getGmtCreateEnd() != null,"",req.getGmtCreateBegin(),req.getGmtCreateEnd());
        queryWrapper.eq(req.getSaleUserId() != null,"sale_user_id",req.getSaleUserId());
        queryWrapper.like(StringUtils.isNotBlank(req.getBillNumber()),"bill_number",req.getBillNumber());
        queryWrapper.like(StringUtils.isNotBlank(req.getProductName()),"product_name",req.getProductName());
        queryWrapper.eq(req.getBillType() != null,"bill_type",req.getBillType());
        queryWrapper.in(req.getBusinessType() != null && req.getBusinessType().size() > 0,"business_type",req.getBusinessType());
        Page<FinanceBill> page = billMapper.selectPage(iPage, queryWrapper);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        List<BillToConfirmListDTO> list = new ArrayList<>();
        page.getRecords().forEach(item -> {
            BillToConfirmListDTO dto = EntityUtil.copy(item,BillToConfirmListDTO.class);
            if (item.getSaleUserId() != null){
                UserDTO userDto = sysUserService.queryCacheUser(item.getSaleUserId());
                if (userDto != null){
                    dto.setSaleDept(userDto.getDept());
                }
            }
            list.add(dto);
        });
        PageResponse<BillToConfirmListDTO> result = new PageResponse<>(
                list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 对账详情-关联认款列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillToConfirmListDTO>> checkList(BillCheckIdListReq req) {
        Page<BillToConfirmListDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        Page<BillToConfirmListDTO> page = billMapper.queryListByCheck(iPage,req.getCheckId());
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        page.getRecords().forEach(item -> {
            if (item.getId() != null && item.getSaleUserId() != null){
                UserDTO userDto = sysUserService.queryCacheUser(item.getSaleUserId());
                if (userDto != null){
                    item.setSaleDept(userDto.getDept());
                }
            }
        });
        PageResponse<BillToConfirmListDTO> result = new PageResponse<>(
                page.getRecords(),
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 销售订单退款列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillRefundListDTO>> refundList(BillRefundListReq req) {
        Page<BillRefundListDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        Page<BillRefundListDTO> page = billMapper.queryRefundListByCondition(iPage,req);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        page.getRecords().forEach(dto -> {
            if (dto.getSaleUserId() != null){
                //销售
                UserDTO userDto = sysUserService.queryCacheUser(dto.getSaleUserId());
                if (userDto != null){
                    dto.setSaleUserDept(userDto.getDept());
                }
            }
            if (StringUtils.isNotBlank(dto.getRefundAccountJson())){
                //退款账户JSON
                AccountJson accountJson = JSON.parseObject(dto.getRefundAccountJson(), AccountJson.class);
                dto.setAccountJson(accountJson);
            }
        });
        PageResponse<BillRefundListDTO> result = new PageResponse<>(
                page.getRecords(),
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 退款-退款信息
     *
     * @param req
     * @return
     */
    @Override
    public Result<BillRefundInfoDTO> addRefundInfo(BillIdReq req) {
        FinanceBill bill = getById(req.getBillId());
        if (bill == null || Objects.equals(bill.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17009);
        }
        BillRefundInfoDTO dto = EntityUtil.copy(bill,BillRefundInfoDTO.class);
        if (StringUtils.isNotBlank(bill.getRefundAccountJson())){
            //退款账户JSON
            AccountJson accountJson = JSON.parseObject(bill.getRefundAccountJson(), AccountJson.class);
            dto.setAccountJson(accountJson);
        }
        //附件
        if (StringUtils.isNotBlank(bill.getPayVoucherJson())){
            List<FileJson> fileJsons = JSON.parseArray(bill.getPayVoucherJson(), FileJson.class);
            dto.setPayVoucherJson(fileJsons);
        }
        return Result.success(dto);
    }

    /**
     * 销售订单退款-退款信息
     *
     * @param req
     * @return
     */
    @Override
    public Result<BillRefundInfoDTO> refundInfo(BillIdReq req) {
        FinanceBill bill = getById(req.getBillId());
        if (bill == null || Objects.equals(bill.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17009);
        }
        BillRefundInfoDTO dto = EntityUtil.copy(bill,BillRefundInfoDTO.class);
        if (StringUtils.isNotBlank(bill.getRefundAccountJson())){
            //退款账户JSON
            AccountJson accountJson = JSON.parseObject(bill.getRefundAccountJson(), AccountJson.class);
            dto.setAccountJson(accountJson);
        }
        //附件
        if (StringUtils.isNotBlank(bill.getPayVoucherJson())){
            List<FileJson> fileJsons = JSON.parseArray(bill.getPayVoucherJson(), FileJson.class);
            dto.setPayVoucherJson(fileJsons);
        }
        //退款信息
        try {
            Integer businessType = bill.getBusinessType();
            Result<List<OrderRefundDTO>> result = new Result<>();
            if (Objects.equals(businessType,SystemBusinessType.OUTBOUND_CUSTOMIZATION.getCode()) ||
                    Objects.equals(businessType,SystemBusinessType.INBOUND_CUSTOMIZATION.getCode()) ||
                    Objects.equals(businessType,SystemBusinessType.CONFERENCE_AWARDS.getCode())){
                //定制包团
                result = customizedOrderTouristRefundService.refundDetailList(bill.getBillNumber());
            }else if (Objects.equals(businessType,SystemBusinessType.OUTBOUND_TRAVEL.getCode()) ||
                    Objects.equals(businessType,SystemBusinessType.INBOUND_TRAVEL.getCode())){
                //旅行团
                result = seriesOrderTouristRefundService.refundDetailList(bill.getBillNumber());
            }else if (Objects.equals(businessType,SystemBusinessType.AIR_TICKET.getCode())){
                //机票
                result = airOrderService.getOrderRefundList(bill.getBillNumber());
            }else if (Objects.equals(businessType,SystemBusinessType.HOTEL.getCode())){
                //酒店
                result = hotelOrderCenterService.financeRefundList(bill.getSaleOrderId());
            }else if (Objects.equals(businessType,SystemBusinessType.ATTRACTION_TICKET.getCode())){
                //景點門票
                result = scenicOrderRefundService.getRefundList(bill.getSaleOrderNumber());
            }else if (Objects.equals(businessType,SystemBusinessType.AIR_EXPRESS.getCode())){
                //機場快線
                List<OrderRefundDTO> refundList = airportExpressOrderService.getRefundList(bill.getSaleOrderNumber());
                if (CollectionUtils.isNotEmpty(refundList)){
                    result.setData(refundList);
                    result.setCode(0);
                }
            }else if (Objects.equals(businessType,SystemBusinessType.LOCAL_FUN.getCode())){
                //当地玩乐
                result = localFunOrderRefundService.refundRecords(bill.getSaleOrderId());
            }else if (Objects.equals(businessType,SystemBusinessType.BUS_TICKET.getCode())){
                //巴士
                List<OrderRefundDTO> refundList = busOrderService.getRefundList(bill.getSaleOrderNumber());
                if (CollectionUtils.isNotEmpty(refundList)){
                    result.setData(refundList);
                    result.setCode(0);
                }
            }else if (Objects.equals(businessType,SystemBusinessType.SHIP_TICKET.getCode())){
                //船票
                result = shipOrderService.refundRecords(bill.getSaleOrderId());
            }else if (Objects.equals(businessType,SystemBusinessType.TRAIN_TICKET.getCode())){
                //火车票
                List<OrderRefundDTO> refundList = trainOrderService.getRefundList(bill.getSaleOrderNumber());
                if (CollectionUtils.isNotEmpty(refundList)){
                    result.setData(refundList);
                    result.setCode(0);
                }
            }else if (Objects.equals(businessType,SystemBusinessType.COMMODITY.getCode())){
                //商品
                CommodityOrderRefundReq refundReq = new CommodityOrderRefundReq();
                refundReq.setOrderId(bill.getSaleOrderId());
                result = orderCommodityRefundService.refundList(refundReq);
            }
            if (result == null || result.getCode() != 0){
                throw new BusinessException(SystemError.SYS_437);
            }
            dto.setRefundList(result.getData());
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(dto);
    }

    /**
     * 销售订单退款-退款
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result refund(BillRefundReq req) {
        FinanceBill bill = getById(req.getBillId());
        if (bill == null || Objects.equals(bill.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17009);
        }
        bill.setRefundTime(req.getRefundTime());
        bill.setRefundRemark(req.getRefundRemark());
        //附件
        if (req.getPayVoucherJson().size() > 0){
            bill.setPayVoucherJson(JSON.toJSONString(req.getPayVoucherJson()));
        }
        bill.setModifiedId(req.getUser().getId());
        //直接设为已确认
        bill.setRefundStatus(1);
        bill.setRefundConfirmStatus(1);
        boolean bl = updateById(bill);
        if (!bl){
            throw new BusinessException(SystemError.SYS_437);
        }

        //是否回滚挂账额度
        RollBackQuotaReq rollBackQuotaReq = new RollBackQuotaReq();
        //退款方式
        Long refundWayId = bill.getRefundWayId();
        if (Objects.equals(CollectionWayCode.ON_ACCOUNT.getCode(),refundWayId) || Objects.equals(CollectionWayCode.INTERNAL_ACCOUNT.getCode(),refundWayId)){
            //挂账或内部挂账
            rollBackQuotaReq = packQuotaRollAddReq(bill,req.getUser().getId());
        }
        if (rollBackQuotaReq != null){
            Result result = financeOnAccountCurrencyQuotaService.rollBackQuota(rollBackQuotaReq);
            if (!result.isSuccess()){
                throw new BusinessException(SystemError.SYS_437);
            }
        }

        //根据收退款单号和业务类型，调用退款接口
        try {
            Integer businessType = bill.getBusinessType();
            Result result = null;
            if (Objects.equals(businessType, SystemBusinessType.AIR_TICKET.getCode())){
                //机票
                result = airOrderService.refundConfirm(bill.getBillNumber(), req.getUser());
            }else if (Objects.equals(businessType,SystemBusinessType.OUTBOUND_CUSTOMIZATION.getCode()) ||
                    Objects.equals(businessType,SystemBusinessType.INBOUND_CUSTOMIZATION.getCode()) ||
                    Objects.equals(businessType,SystemBusinessType.CONFERENCE_AWARDS.getCode())) {
                //定制包团
                result = customizedOrderTouristRefundService.confirmRefund(bill.getBillNumber(), req.getUser());
            }else if (Objects.equals(businessType,SystemBusinessType.OUTBOUND_TRAVEL.getCode()) ||
                    Objects.equals(businessType,SystemBusinessType.INBOUND_TRAVEL.getCode())) {
                //旅行团
                result = seriesOrderTouristRefundService.confirmRefund(bill.getBillNumber(), req.getUser());
            }else if (Objects.equals(businessType,SystemBusinessType.HOTEL.getCode())){
                //酒店
                result = hotelOrderCenterService.financeConfirmRefund(bill.getBillNumber(),req.getUser().getId());
            }else if (Objects.equals(businessType,SystemBusinessType.ATTRACTION_TICKET.getCode())) {
                //门票
                result = scenicOrderRefundService.operateRefund(bill.getBillNumber(), req.getUser().getId());
            }else if (Objects.equals(businessType,SystemBusinessType.AIR_EXPRESS.getCode())){
                //机场快线
                result = airportExpressOrderRefundService.confirmRefund(bill.getBillNumber(), req.getUser().getId());
            }else if (Objects.equals(businessType,SystemBusinessType.LOCAL_FUN.getCode())){
                //当地玩乐
                result = localFunOrderRefundService.confirmRefund(bill.getBillNumber(), req.getUser().getId());
            }else if (Objects.equals(businessType,SystemBusinessType.BUS_TICKET.getCode())){
                //巴士
                result = busOrderRefundService.confirmRefund(bill.getBillNumber(), req.getUser().getId());
            }else if (Objects.equals(businessType,SystemBusinessType.SHIP_TICKET.getCode())){
                //船票
                result = shipOrderService.confirmRefund(bill.getBillNumber(), req.getUser().getId());
            }else if (Objects.equals(businessType,SystemBusinessType.TRAIN_TICKET.getCode())){
                //火车票
                result = trainOrderRefundService.confirmRefund(bill.getBillNumber(), req.getUser().getId());
            }else if (Objects.equals(businessType,SystemBusinessType.COMMODITY.getCode())) {
                //商品
                result = orderService.updateRefundStatus(bill.getSaleOrderId(), req.getUser());
            }
            if (result == null || !result.isSuccess()){
                return result;
            }
        }catch (Exception e){
            log.error("【财务模块-确认退款】异常", e);
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(bill.getId());
    }

    /**
     * 封装回滚挂账额度请求参数
     * @param bill
     * @param userId
     * @return
     */
    private RollBackQuotaReq packQuotaRollAddReq(FinanceBill bill, Long userId) {
        RollBackQuotaReq rollBackQuotaReq = new RollBackQuotaReq();
        rollBackQuotaReq.setOrderId(bill.getSaleOrderId());
        rollBackQuotaReq.setRefundNumber(bill.getBillNumber());
        rollBackQuotaReq.setAmount(bill.getCollectionAmount());
        rollBackQuotaReq.setBusinessType(bill.getBusinessType());
        rollBackQuotaReq.setUserId(userId);
        return rollBackQuotaReq;
    }

    /**
     * 销售订单退款-确认
     *
     * @param req
     * @return
     */
    @Override
    public Result confirmRefund(BillIdReq req) {
        FinanceBill bill = getById(req.getBillId());
        if (bill == null || Objects.equals(bill.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17009);
        }
        //已退款&待确认
        if (!Objects.equals(bill.getRefundStatus(),1) || !Objects.equals(bill.getRefundConfirmStatus(),0)){
            throw new BusinessException(SystemError.FINANCE_BILL_17018);
        }
        bill.setRefundConfirmStatus(1);
        bill.setModifiedId(req.getUserId());
        boolean bl = updateById(bill);
        if (!bl){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(bill.getId());
    }

    /**
     * 新增收款认款(内部接口)
     *
     * @param reqList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result addCollection(List<BillAddCollectionReq> reqList) {
        List<FinanceBill> list = new ArrayList<>();
        List<Long> idList = new ArrayList<>();
        List<FinanceBillGroupRecord> recordList = new ArrayList<>();
        if (reqList != null && reqList.size() > 0){
            reqList.forEach(req -> {
                FinanceBill bill = EntityUtil.copy(req,FinanceBill.class);
                bill.setId(SnowflakeIdWorker.nextId());
                bill.setCheckBillStatus(0);
                bill.setOffAccountStatus(0);
                bill.setBillType(1);
                List<FileJson> collectionVoucherJsonList = req.getCollectionVoucherJsonList();
                if (collectionVoucherJsonList != null && collectionVoucherJsonList.size() > 0){
                    bill.setCollectionVoucherJson(JSON.toJSONString(collectionVoucherJsonList));
                }
                if (req.getProductId() != null && req.getProductId().size() > 0){
                    bill.setProductId(JSON.toJSONString(req.getProductId()));
                }
                if (req.getResourceInfo() != null && req.getResourceInfo().size() > 0){
                    bill.setResourceInfo(JSON.toJSONString(req.getResourceInfo()));
                }
                bill.setIsReject(0);
                bill.setGmtCreate(LocalDateTime.now());
                bill.setIsDeleted(0);
                bill.setCreateId(req.getUserId());
                list.add(bill);
                idList.add(bill.getId());

                //团期认款记录
                int businessType = req.getBusinessType().intValue();
                Integer groupType = null;
                //收款类型（1：团费,2：保险）
                int type = 1;
                if (Objects.equals(bill.getCollectionWayId(), CollectionWayIdCode.INSURANCE.getCode())){
                    type = 2;
                }
                if (businessType == 1 || businessType == 2){
                    groupType = 1;
                }else if (businessType == 3 || businessType == 4 || businessType == 5){
                    groupType = 2;
                }
                FinanceBillGroupRecord record = packBillGroupCollectRecord(bill,groupType,1,type,req.getScheduleId());
                recordList.add(record);
            });
        }
        //批量新增
        if (list.size() > 0){
            Integer batch = billMapper.insertBatchSomeColumn(list);
            if (batch < list.size()){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        //批量新增团期认款记录
        if (recordList.size() > 0){
            Integer batch = billGroupRecordMapper.insertBatchSomeColumn(recordList);
            if (batch < recordList.size()){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        return Result.success(idList);
    }

    /**
     * 封装团期收款认款记录
     * @param bill
     * @param groupType
     * @param adjustType
     * @param type
     * @return
     */
    private FinanceBillGroupRecord packBillGroupCollectRecord(FinanceBill bill, Integer groupType,int adjustType,int type,Long scheduleId) {
        LocalDate date = LocalDate.now();
        FinanceBillGroupRecord record = EntityUtil.copy(bill,FinanceBillGroupRecord.class);
        record.setId(SnowflakeIdWorker.nextId());
        record.setScheduleId(scheduleId);
        record.setGroupType(groupType);
        record.setAdjustType(adjustType);
        //查询科目
        MainDataSubjectDTO subjectDTO = mainDataSubjectService.queryByCondition(bill.getBusinessType(), type);
        if (subjectDTO != null){
            record.setSubjectId(subjectDTO.getId());
            record.setSubectNumber(subjectDTO.getNumber());
            record.setSubectType(subjectDTO.getCollectionType());
            record.setType(subjectDTO.getType());
            record.setSummary(DateUtil.fmtLocalDate(date,"dd/MM-yyyy") + subjectDTO.getSummary());
        }
        record.setBillId(bill.getId());
        record.setAddTime(bill.getCollectionTime());
        record.setCurrencyId(bill.getCurrencyId());
        record.setCurrency(bill.getCurrencyName());
        record.setExchangeRate(new BigDecimal(bill.getExchangeRate()));
        record.setAmount(bill.getCollectionAmount());
        record.setHkdAmount(bill.getCollectionAmount().multiply(new BigDecimal(bill.getExchangeRate())).setScale(2,BigDecimal.ROUND_HALF_UP));
        if (bill.getSaleUserId() != null){
            UserDTO userDTO = sysUserService.queryCacheUser(bill.getSaleUserId());
            record.setSaleDeptCode(userDTO.getDeptCode());
            record.setCostCode(userDTO.getDeptCostCode());
        }
        record.setIsExport(0);
        record.setCreateDate(date);
        record.setCreateId(bill.getCreateId());
        record.setGmtCreate(LocalDateTime.now());
        record.setIsDeleted(0);
        return record;
    }

    /**
     * 封装团期退款认款记录
     * @param bill
     * @param groupType
     * @param adjustType
     * @param type
     * @param scheduleId
     * @return
     */
    private FinanceBillGroupRecord packBillGroupRefundRecord(FinanceBill bill, int groupType,int adjustType,int type,Long scheduleId) {
        FinanceBillGroupRecord record = EntityUtil.copy(bill,FinanceBillGroupRecord.class);
        LocalDate date = LocalDate.now();
        record.setId(SnowflakeIdWorker.nextId());
        record.setScheduleId(scheduleId);
        record.setGroupType(groupType);
        record.setAdjustType(adjustType);
        //查询科目
        MainDataSubjectDTO subjectDTO = mainDataSubjectService.queryByCondition(bill.getBusinessType(), type);
        if (subjectDTO != null){
            record.setSubjectId(subjectDTO.getId());
            record.setSubectNumber(subjectDTO.getNumber());
            record.setSubectType(subjectDTO.getCollectionType());
            record.setType(subjectDTO.getType());
            record.setSummary(DateUtil.fmtLocalDate(date,"dd/MM-yyyy") + subjectDTO.getSummary());
        }
        record.setBillId(bill.getId());
        record.setAddTime(bill.getCollectionTime());
        record.setCurrencyId(bill.getCurrencyId());
        record.setCurrency(bill.getCurrencyName());
        record.setExchangeRate(new BigDecimal(bill.getExchangeRate()));
        record.setAmount(bill.getCollectionAmount());
        record.setHkdAmount(bill.getCollectionAmount().multiply(new BigDecimal(bill.getExchangeRate())).setScale(2,BigDecimal.ROUND_HALF_UP));
        if (bill.getSaleUserId() != null){
            UserDTO userDTO = sysUserService.queryCacheUser(bill.getSaleUserId());
            record.setSaleDeptCode(userDTO.getDeptCode());
            record.setCostCode(userDTO.getDeptCostCode());
        }
        record.setCollectionTypeId(bill.getRefundTypeId());
        record.setCollectionType(bill.getRefundType());
        record.setCollectionWayId(bill.getRefundWayId());
        record.setCollectionWay(bill.getRefundWay());
        record.setIsExport(0);
        record.setCreateDate(date);
        record.setCreateId(bill.getCreateId());
        record.setGmtCreate(LocalDateTime.now());
        record.setIsDeleted(0);
        return record;
    }

    /**
     * 新增退款认款(内部接口)
     *
     * @param reqList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result addRefund(List<BillAddRefundReq> reqList) {
        List<FinanceBill> list = new ArrayList<>();
        List<Long> idList = new ArrayList<>();
        List<FinanceBillGroupRecord> recordList = new ArrayList<>();
        if (reqList != null && reqList.size() > 0){
            reqList.forEach(req -> {
                FinanceBill bill = EntityUtil.copy(req,FinanceBill.class);
                bill.setId(SnowflakeIdWorker.nextId());
                bill.setBillType(2);
                //退款账户
                if (req.getRefundAccountJson() != null){
                    bill.setRefundAccountJson(JSON.toJSONString(req.getRefundAccountJson()));
                }
                //附件
                List<FileJson> payVoucherJson = req.getPayVoucherJson();
                if (payVoucherJson != null && payVoucherJson.size() > 0){
                    bill.setPayVoucherJson(JSON.toJSONString(payVoucherJson));
                }
                if (req.getProductId() != null && req.getProductId().size() > 0){
                    bill.setProductId(JSON.toJSONString(req.getProductId()));
                }
                if (req.getResourceInfo() != null && req.getResourceInfo().size() > 0){
                    bill.setResourceInfo(JSON.toJSONString(req.getResourceInfo()));
                }
                bill.setRefundTypeId(req.getTypeId());
                bill.setRefundType(req.getType());
                bill.setRefundWayId(req.getRefundTypeId());
                bill.setRefundWay(req.getRefundType());
                bill.setRefundStatus(0);
                bill.setRefundConfirmStatus(0);
                bill.setGmtCreate(LocalDateTime.now());
                bill.setIsDeleted(0);
                bill.setCreateId(req.getUserId());
                list.add(bill);
                idList.add(bill.getId());

                //团期认款记录
                int businessType = req.getBusinessType().intValue();
                int groupType = 1;
                //收款类型（1：团费,2：保险）
                int type = 1;
                if (businessType == 1 || businessType == 2){
                    if (Objects.equals(bill.getRefundWayId(), CollectionWayIdCode.INSURANCE.getCode())){
                        type = 2;
                    }
                    FinanceBillGroupRecord record = packBillGroupRefundRecord(bill,groupType,2,type,req.getScheduleId());
                    recordList.add(record);
                }else if (businessType == 3 || businessType == 4 || businessType == 5){
                    groupType = 2;
                    if (Objects.equals(bill.getRefundWayId(), CollectionWayIdCode.INSURANCE.getCode())){
                        type = 2;
                    }
                    FinanceBillGroupRecord record = packBillGroupRefundRecord(bill,groupType,2,type,req.getScheduleId());
                    recordList.add(record);
                }
            });
        }
        //批量新增
        if (list.size() > 0){
            Integer batch = billMapper.insertBatchSomeColumn(list);
            if (batch < list.size()){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        return Result.success(idList);
    }

    /**
     * 操作退款(内部接口)
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result operateRefund(BillOperateRefundReq req) {
        //查询待退款退款的单号
        QueryWrapper<FinanceBill> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("bill_number",req.getBillNumber());
        queryWrapper.eq("bill_type",2);
        queryWrapper.eq("business_type",req.getBusinessType());
        queryWrapper.eq("is_deleted",0);
        queryWrapper.eq("refund_status",0);
        queryWrapper.eq("refund_confirm_status",0);
        FinanceBill bill = billMapper.selectOne(queryWrapper);
        if (bill == null){
            throw new BusinessException(SystemError.FINANCE_BILL_17009);
        }
        //已退款&待确认
        bill.setRefundStatus(1);
        bill.setModifiedId(req.getUserId());
        boolean update = updateById(bill);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(bill.getId());
    }

    /**
     * 再次确认(内部接口)
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result reConfirm(BillOperateRefundReq req) {
        //查询认款确认信息
        QueryWrapper<FinanceBill> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("bill_number",req.getBillNumber());
        queryWrapper.eq("business_type",req.getBusinessType());
        queryWrapper.eq("bill_type",1);
        queryWrapper.eq("is_deleted",0);
        FinanceBill bill = billMapper.selectOne(queryWrapper);
        if (bill == null){
            throw new BusinessException(SystemError.FINANCE_BILL_17009);
        }
        if (!Objects.equals(bill.getIsReject(),1)){
            throw new BusinessException(SystemError.FINANCE_ERROR_17038);
        }
        bill.setModifiedId(req.getUserId());
        bill.setIsReject(0);
        boolean update = updateById(bill);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(bill.getBillNumber());
    }

}
